colorscheme gruvbox-light

source "%val{config}/plugins/plug.kak/rc/plug.kak"

# plugins

plug "andreyorst/plug.kak" noload
plug "https://gitlab.com/Screwtapello/kakoune-state-save"
# plug "andreyorst/powerline.kak" defer "powerline" %{
    # powerline-separator triangle
    # set-option global powerline_format 'powerline-format git bufname filetype mode_info line_column position'
    # powerline-toggle line_column off
    # powerline-theme gruvbox
# }
plug "andreyorst/powerline.kak" defer powerline %{
    set-option global powerline_ignore_warnings true
    set-option global powerline_format 'git bufname langmap smarttab mode_info filetype client session position'
    powerline-theme gruvbox-light
}
plug "andreyorst/kakoune-snippet-collection"
plug "delapouite/kakoune-text-objects"
plug "occivink/kakoune-vertical-selection"
plug "occivink/kakoune-sudo-write"
plug "occivink/kakoune-find" config %{
    define-command -docstring "grep-apply-changes: apply changes specified in current *grep* buffer to their respective files" \
    grep-apply-changes %{ find-apply-changes -force }
}
plug "andreyorst/smarttab.kak" %{
    set-option global softtabstop 4
    hook global WinSetOption filetype=(rust|markdown|kak|lisp|scheme|sh|perl) expandtab
    hook global WinSetOption filetype=(makefile|gas) noexpandtab
    hook global WinSetOption filetype=(c|cpp) smarttab
}
plug "alexherbo2/auto-pairs.kak" %{
    map global user 's' ': auto-pairs-surround<ret>' -docstring "surround selection"
}

plug "alexherbo2/replace.kak" config %{
    map global user r -docstring 'Replace mode' ':<space>replace<ret>'
}

plug "alexherbo2/move-line.kak" config %{
    map global normal '<a-up>'   ': move-line-above %val{count}<ret>'
    map global normal '<a-down>' ': move-line-below %val{count}<ret>'
}

plug "andreyorst/kakoune-snippets" branch "auto-discard" config %{
    set-option -add global snippets_directories "%opt{plug_install_dir}/kakoune-snippet-collection/snippets"
    set-option global snippets_auto_expand false
    map global insert '<tab>' "<a-;>: expand-or-jump-or-key tab<ret>"
    map global insert '<ret>' "<a-;>: expand-or-jump-or-key ret<ret>"
    map global normal '<tab>' ":      expand-or-jump-or-key tab<ret>"
    map global normal '<ret>' ":      expand-or-jump-or-key ret<ret>"

    define-command -docstring "expand-or-jump-or-key <key>: expand snippet or jump to the placeholder or execute <key>" \
    expand-or-jump-or-key -params 1 %{
        try %{ snippets-expand-trigger %{
            set-register / "%opt{snippets_triggers_regex}\z"
            execute-keys 'hGhs<ret>'
        }} catch %{
            snippets-select-next-placeholders
        } catch %sh{
            printf "%s\n" "execute-keys -with-hooks <$1>"
        }
    }
}

plug "ul/kak-lsp" do %{
    cargo build --release --locked
    cargo install --force --path .
} config %{
    define-command lsp-restart %{ lsp-stop; lsp-start }
    set-option global lsp_completion_trigger "execute-keys 'h<a-h><a-k>\S[^\s,=;*(){}\[\]]\z<ret>'"
    set-option global lsp_diagnostic_line_error_sign "!"
    set-option global lsp_diagnostic_line_warning_sign "?"
    hook global WinSetOption filetype=(c|cpp|rust) %{
        map window user "l" ": enter-user-mode lsp<ret>" -docstring "LSP mode"
        lsp-enable-window
        lsp-auto-hover-enable
        lsp-auto-hover-insert-mode-disable
        set-option window lsp_hover_anchor true
        set-face window DiagnosticError default+u
        set-face window DiagnosticWarning default+u
    }
    hook global WinSetOption filetype=rust %{
        set-option window lsp_server_configuration rust.clippy_preference="on"
    }
    hook global KakEnd .* lsp-exit
}

plug "andreyorst/tagbar.kak" defer tagbar %{
    set-option global tagbar_sort false
    set-option global tagbar_size 40
    set-option global tagbar_display_anon false
} config %{
    map global user 't' ": tagbar-toggle<ret>" -docstring "toggle tagbar panel"
    hook global WinSetOption filetype=(c|cpp|rust|gas|markdown) %{
        tagbar-enable
    }
    hook global WinSetOption filetype=tagbar %{
        remove-highlighter buffer/numbers
        remove-highlighter buffer/matching
        remove-highlighter buffer/wrap
        remove-highlighter buffer/show-whitespaces
    }
}

plug "alexherbo2/word-movement.kak" config %{
    word-movement-map next w
    word-movement-map previous b
}

plug "alexherbo2/yank-ring.kak" config %{
    map -docstring "yank-ring" global user 'Y' ': yank-ring<ret>'
}

plug "alexherbo2/split-object.kak" config %{
    map -docstring "split object" global normal '<a-I>' ': enter-user-mode split-object<ret>'
}

plug "screwtapello/kakoune-inc-dec" domain GitLab.com config %{
    map -docstring "decrement selection" global normal '<C-x>' ': inc-dec-modify-numbers - %val{count}<ret>'
    map -docstring "increment selection" global normal '<C-a>' ': inc-dec-modify-numbers + %val{count}<ret>'
}

plug "delapouite/kakoune-select-view" %{
    # Suggested mappings
    map global normal <a-%> ': select-view<ret>' -docstring 'select view'
    map global view s '<esc>: select-view<ret>' -docstring 'select view'
}

# Common options
set-option global scrolloff 4,4

# Grep
evaluate-commands %sh{
    [ ! -z "$(command -v rg)" ] && printf "%s\n" "set-option global grepcmd 'rg -L --hidden --with-filename --column'"
}

set-option global makecmd 'make --jobs=4'

# scroll offset
set global scrolloff 12,0

# 4-space tabs
set global indentwidth 4
set global tabstop 4

hook global BufSetOption filetype=.*?(haskell|ruby) %{
    set buffer tabstop 2
    set buffer indentwidth 2
}
hook global InsertChar \t %{ exec -draft -itersel h@ }

# backspace removes 4 spaces
map global insert <backspace> ⌫
hook global InsertChar ⌫ %{ try %{
    execute-keys <backspace>
    try %{
        execute-keys -draft hGh <a-k>\A\h+\z<ret> <lt>
        } catch %{
            execute-keys <backspace>
        }
     }
}

# Align with spaces
hook global WinCreate .* %{
    set-option window aligntab false
}

# Use main client as jumpclient
set-option global jumpclient client0

# Highlighters
set-face global delimiter rgb:aa3a03

hook global WinCreate .* %{
    try %{
        add-highlighter buffer/numbers          number-lines -relative -hlcursor -separator ' '
        add-highlighter buffer/matching         show-matching
        add-highlighter buffer/wrap             wrap -word -indent -marker '↪'
        add-highlighter buffer/show-whitespaces show-whitespaces -lf ' ' -spc ' ' -nbsp '⋅'
        add-highlighter buffer/operators        regex (\+|-|\*|&|=|\\|\?|%|\|-|!|\||->|\.|,|<|>|:|\^|/|~) 0:operator
        add-highlighter buffer/delimiters       regex (\(|\)|\[|\]|\{|\}|\;|'|`) 0:delimiter
    }
}

add-highlighter global/VisibleWords regex \b(?:FIXME|TODO|XXX)\b 0:rgb:cc241d

# Hooks

## Editorconfig
hook global BufOpenFile .* editorconfig-load
hook global BufNewFile  .* editorconfig-load

# Aliases
alias global h doc

# Scratch buffer

## Delete the `*scratch*' buffer as soon as another is created, but only if it's empty
hook global BufCreate '^\*scratch\*$' %{
    execute-keys -buffer *scratch* '%d'
    hook -once -always global BufCreate '^(?!\*scratch\*).*$' %{ try %{
        # throw if the buffer has more than one character
        execute-keys -buffer *scratch* 'L<a-K>..<ret>'
        delete-buffer *scratch*
    }}
}

# vim old habits
map global normal D '<a-l>d' -docstring 'delete to end of line'
map global normal Y '<a-l>y' -docstring 'yank to end of line'
map global normal C '<a-l>di' -docstring 'change to end of line'
map global normal <a-D> '<a-h>d' -docstring 'delete from beginning of line'
map global normal <a-Y> '<a-h>y' -docstring 'yank from beginning of line'
map global normal <a-C> '<a-h>c' -docstring 'change from beginning of line'

map global normal = :format<ret> -docstring 'format buffer'

map global normal '#' :comment-line<ret> -docstring 'comment line'
map global normal '<a-#>' :comment-block<ret> -docstring 'comment block'

map global user p '!pbpaste<ret>' -docstring "paste after"
map global user P '<a-!>pbpaste<ret>' -docstring "paste before"

# (case-insensitive) search
map global user / '/(?i)' -docstring 'case-insensitive search'
map global user s 's(?i)' -docstring 'case-insensitive select'

# <a-x> does not select the next line on multiple presses
# map global normal <x> <a-x>
# map global normal <a-x> <x>

# Select all occurences of the main selection
map global user a '*%s<ret>' -docstring "select all"

# Show length of selection
# map global user s ':selection-length<ret>' -docstring "selection length"

# Trim all whitespaces
map global user t ':trim-whitespaces<ret>' -docstring "trim whitespaces"

# Extend selections
map global user x ':extend-line-down %val{count}<ret>' -docstring "extend line down"
map global user X ':extend-line-up %val{count}<ret>' -docstring "extend line up"

# add line numbers
add-highlighter global/number-lines number-lines -relative -hlcursor

# auto wrap for markdown
hook global WinCreate .*[.](md|tex|rst) %{
        set buffer autowrap_column 80
            autowrap-enable
}

# add brackets highlighting
hook global KakBegin .* %{addhl global/ show-matching}


# highlight trailing whitespace at the end of lines
hook -group TrailingWhitespaces global KakBegin .* %{
    addhl global/ regex "[ \t]+$" 0:default,red
}

define-command trim-whitespaces %{
   try %{
        exec -draft '%s\h+$<ret>d'
    } catch %{
    }
}

hook global BufWritePre .* trim-whitespaces

# Commands

define-command -docstring \
"select a word under cursor, or add cursor on next occurrence of current selection" \
select-or-add-cursor %{ execute-keys -save-regs '' %sh{
    if [ $(printf "%s\n" ${kak_selection} | wc -m) -eq 2 ]; then
        printf "%s\n" "<a-i>w*"
    else
        printf "%s\n" "*<s-n>"
    fi
}}

define-command -docstring "split tmux vertically" \
vsplit -params .. -command-completion %{
    tmux-terminal-horizontal kak -c %val{session} -e "%arg{@}"
}

define-command -docstring "split tmux horizontally" \
split -params .. -command-completion %{
    tmux-terminal-vertical kak -c %val{session} -e "%arg{@}"
}

define-command -docstring "create new tmux window" \
tabnew -params .. -command-completion %{
    tmux-terminal-window kak -c %val{session} -e "%arg{@}"
}

define-command -docstring "print current working directory" \
pwd %{ evaluate-commands %sh{
    printf "%s\n" "echo -markup %{{Information}${PWD}}"
}}

# Normal mode mappings
map -docstring "add currsor/jump on current word"    global normal '<c-d>' ': select-or-add-cursor<ret>'

# System clipboard mappings
map -docstring "copy to system clipboard"                   global user 'y' '<a-|>pbcopy<ret>'
map -docstring "cut to system clipboard, enter insert mode" global user 'c' '|pbcopy<ret>'
map -docstring "paste from system clipboard before cursor"  global user 'P' '!pbpaste<ret>'
map -docstring "paste from system clipboard after cursor"   global user 'p' '<a-!>pbpaste<ret>'
map -docstring "replace selection with system clipboard"    global user 'r' '|pbpaste<ret>'

# Insert Mode Mappings Completion

hook global InsertCompletionShow .* %{ try %{
    execute-keys -draft 'h<a-K>\h<ret>'
    map window insert <tab> <c-n>
    map window insert <s-tab> <c-p>
}}

hook global InsertCompletionHide .* %{
    unmap window insert <tab> <c-n>
    unmap window insert <s-tab> <c-p>
}

# Goto mode mappings
map -docstring "file (non-recursive)"           global goto '<a-f>' '<esc>gf'
map -docstring "file (recursive)"               global goto 'f'     '<esc>: smart-select WORD; search-file %val{selection}<ret>'
map -docstring "next buffer"                    global goto 'b'     '<esc>: buffer-next<ret>'
map -docstring "previous buffer"                global goto 'B'     '<esc>: buffer-previous<ret>'
map -docstring "search tag in current file"     global goto '['     '<esc><c-s>: smart-select word; symbol<ret>'
map -docstring "search tag in global tags file" global goto ']'     '<esc><c-s>: smart-select word; ctags-search<ret>'
map -docstring 'matching char'                  global goto 'm'     '<esc>m;'
